package pgorm

import (
	"fmt"
	"time"

	"gorm.io/driver/postgres"
	"gorm.io/gorm"
	"gorm.io/gorm/clause"
	"gorm.io/gorm/logger"
)

// DBConfig 数据库配置
type DBConfig struct {
	Host     string
	Port     int
	User     string
	Password string
	DBName   string
	PoolSize int // 连接池大小
}

// DBClient 数据库客户端
type DBClient struct {
	db *gorm.DB
}

func InitDBClient(cfg DBConfig) (*DBClient, error) {
	dsn := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=disable",
		cfg.Host, cfg.Port, cfg.User, cfg.Password, cfg.DBName)

	db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{
		Logger: logger.Default.LogMode(logger.Info),
	})
	if err != nil {
		return nil, fmt.Errorf("failed to connect database: %w", err)
	}

	sqlDB, err := db.DB()
	if err != nil {
		return nil, fmt.Errorf("failed to get underlying DB: %w", err)
	}

	// 设置连接池
	sqlDB.SetMaxIdleConns(10)
	sqlDB.SetMaxOpenConns(cfg.PoolSize)
	sqlDB.SetConnMaxLifetime(time.Hour)

	return &DBClient{db: db}, nil
}

// AutoMigrate 自动迁移模型
func (c *DBClient) AutoMigrate(models ...interface{}) error {
	return c.db.AutoMigrate(models...)
}

// Create 创建记录
func (c *DBClient) Create(model interface{}) error {
	return c.db.Create(model).Error
}

// FindByID 根据ID查找
func (c *DBClient) FindByID(model interface{}, id interface{}) error {
	return c.db.First(model, id).Error
}

func (c *DBClient) Find(model interface{}, page int, pageSize int, sort string, desc bool, conds ...interface{}) error {
	offset := (page - 1) * pageSize
	return c.db.Order(clause.OrderByColumn{Column: clause.Column{Name: sort}, Desc: desc}).Limit(pageSize).Offset(offset).Find(model, conds).Error
}

// UpdateByID, if not found return err gorm.ErrRecordNotFound
func (c *DBClient) UpdateByID(model interface{}, id interface{}) error {
	err := c.FindByID(model, id)
	if err != nil {
		return err
	}
	return c.db.Save(model).Error
}

// Update 更新记录，不存在就新增
func (c *DBClient) Update(model interface{}) error {
	return c.db.Save(model).Error
}

// Delete 删除记录: &User{}, map[string]interface{}{"name": "John", "age": 20}
func (c *DBClient) Delete(model interface{}, conds ...interface{}) error {
	return c.db.Delete(model).Error
}

// Query 自定义查询: "SELECT * FROM users WHERE age > ? AND name LIKE ?", 18, "%John%"
func (c *DBClient) Query(query string, args ...interface{}) *gorm.DB {
	return c.db.Raw(query, args...)
}

// Transaction 执行事务
func (c *DBClient) Transaction(fn func(tx *DBClient) error) error {
	return c.db.Transaction(func(tx *gorm.DB) error {
		return fn(&DBClient{db: tx})
	})
}

// Close 关闭连接
func (c *DBClient) Close() error {
	sqlDB, err := c.db.DB()
	if err != nil {
		return err
	}
	return sqlDB.Close()
}
